package com.david.kspmodel

import com.google.devtools.ksp.containingFile
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSVisitorVoid
import com.google.devtools.ksp.validate

//参考链接：https://juejin.cn/post/7157881407057559589

/**
 * creator: lt  2022/10/20  lt.dygzs@qq.com
 * effect : ksp处理程序的创建
 * warning:
 */
internal class TestKspSymbolProcessorProvider : SymbolProcessorProvider {
    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor =
        JsBridgeSymbolProcessor(environment)
        //TestKspSymbolProcessor(environment)
}

/**
 * creator: lt  2022/10/20  lt.dygzs@qq.com
 * effect : ksp处理程序
 * warning:
 */
internal class TestKspSymbolProcessor(private val environment: SymbolProcessorEnvironment) : SymbolProcessor {
    override fun process(resolver: Resolver): List<KSAnnotated> {
        val symbols = resolver.getSymbolsWithAnnotation(TestKsp::class.qualifiedName!!)
        val ret = mutableListOf<KSAnnotated>()
        symbols.toList().forEach {
            if (!it.validate())
                ret.add(it)
            else
                it.accept(TestKspVisitor(environment), Unit)//处理符号
        }
        //返回无法处理的符号
        return ret
    }

}


internal class JsBridgeSymbolProcessor(private val environment: SymbolProcessorEnvironment) : SymbolProcessor {
    private val classNames = arrayListOf<String>()

    override fun process(resolver: Resolver): List<KSAnnotated> {
        val symbols = resolver.getSymbolsWithAnnotation(TestKsp::class.qualifiedName!!)
        if (symbols.toList().isNullOrEmpty()) {
            return symbols.toList()
        }
        val ret = mutableListOf<KSAnnotated>()


        val outFilePackageName = "com.david.func_test.jsobject"//获取这个类的包名


        //val originalClassName = classDeclaration?.simpleName?.asString()//获取类名
        val className = "${environment.options["testModuleName"].toString().replace("[^0-9a-zA-Z_]+", "")}JsBridge"
        val file = environment.codeGenerator.createNewFile(//创建新的文件(默认.kt)
            Dependencies(
                false
            ), outFilePackageName, className, "java"
        )

        symbols.toList().forEach {
            if (!it.validate())
                ret.add(it)
            else {
                it.accept(InnerJsBridgeVisitor(), Unit)//处理符号
                //classNames.add(it.toString())
                environment.logger.warn("Package name: ${it.containingFile?.javaClass}")
                //if (it is KSDeclaration) {
                    //file.write("//".toByteArray())
                    //file.write((it).packageName.toString().toByteArray())
                    //file.write("\n".toByteArray())
                    //classNames.add("$packageName.$it")
                //}
            }
        }



        val sb = StringBuilder()
        sb.append("package $outFilePackageName;\n\n")
            .append("import java.util.List; \n")
            .append("import java.util.ArrayList; \n")
            .append("\n")
            .append("\n")
            .append("")
        sb.append("/**\n")
        sb.append(" * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY WEBVIEW JSBRIDGE.\n")
        sb.append(" */\n")

        sb.append("public class ")
        sb.append("$className ")
        sb.append("{\n")
        sb.append("    public static List<Class> mJsObjectNames = new ArrayList<>();\n")
        sb.append("\n")
        sb.append("\n")
        sb.append("    static {\n")

        classNames.forEach { item ->
            sb.append("        mJsObjectNames.add(")
            sb.append("$item.class")
            sb.append(");\n")
        }


        sb.append("    }\n")
        sb.append("}\n")


        //file.write("package $packageName\n\n".toByteArray())//写入文件
        //file.write("class $className {\n".toByteArray())
        //file.write("    val fields = ".toByteArray())
        //val fields = classDeclaration.getAllProperties().map {//遍历所有的属性
        //    val name = it.simpleName.getShortName()//属性名
        //    val type = it.type.resolve().toString()//属性类型
        //    "$name: $type"
        //}.joinToString()
        //file.write("\"$fields ${environment.options["testModuleName"]}\"\n".toByteArray())
        //file.write("}".toByteArray())
        file.write(sb.toString().toByteArray())
        file.close()



        //返回无法处理的符号
        return ret
    }

    inner class InnerJsBridgeVisitor: KSVisitorVoid() {
        override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
            super.visitClassDeclaration(classDeclaration, data)
            environment.logger.warn("packageName: ${classDeclaration.containingFile!!.packageName.asString()}")
            val fileName = classDeclaration.containingFile!!.fileName
            environment.logger.warn("simpleName: ${fileName.substring(0, fileName.indexOf("."))}")
            classNames.add(classDeclaration.containingFile!!.packageName.asString() + "." + fileName.substring(0, fileName.indexOf(".")))
        }
    }
}

internal class JsBridgeVisitor(private val environment: SymbolProcessorEnvironment): KSVisitorVoid() {
    override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
        super.visitClassDeclaration(classDeclaration, data)
        environment.logger.warn("JsBridgeVisitor->visitClassDeclaration")

        //val packageName = classDeclaration.containingFile!!.packageName.asString()//获取这个类的包名
        //val originalClassName = classDeclaration.simpleName.asString()//获取类名
        //val className = "My${originalClassName}"
        //val file = environment.codeGenerator.createNewFile(//创建新的文件(默认.kt)
        //    Dependencies(
        //        true,
        //        classDeclaration.containingFile!!
        //    ), packageName, className, "java"
        //)
        //val sb = StringBuilder()
        //sb.append("package $packageName;\n\n")
        //    .append("import java.util.List; \n")
        //    .append("import java.util.ArrayList; \n")
        //    .append("\n")
        //    .append("\n")
        //    .append("")
        //sb.append("/**\n")
        //sb.append(" * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY WEBVIEW JSBRIDGE.\n")
        //sb.append(" */\n")
        //
        //sb.append("public class ")
        //sb.append("$className ")
        //sb.append("{\n")
        //sb.append("    public static List<Class> mJsObjectNames = new ArrayList<>();\n")
        //sb.append("\n")
        //sb.append("\n")
        //sb.append("    static {\n")
        //sb.append("    }\n")
        //sb.append("}\n")


        //file.write("package $packageName\n\n".toByteArray())//写入文件
        //file.write("class $className {\n".toByteArray())
        //file.write("    val fields = ".toByteArray())
        //val fields = classDeclaration.getAllProperties().map {//遍历所有的属性
        //    val name = it.simpleName.getShortName()//属性名
        //    val type = it.type.resolve().toString()//属性类型
        //    "$name: $type"
        //}.joinToString()
        //file.write("\"$fields ${environment.options["kspcompileargname"]}\"\n".toByteArray())
        //file.write("}".toByteArray())
        //file.write(sb.toString().toByteArray())
        //file.close()
    }
}


/**
 * creator: lt  2022/10/20  lt.dygzs@qq.com
 * effect : 访问并处理相应符号
 * warning:
 */
internal class TestKspVisitor(private val environment: SymbolProcessorEnvironment) : KSVisitorVoid() {
    override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
        val packageName = classDeclaration.containingFile!!.packageName.asString()//获取这个类的包名
        val originalClassName = classDeclaration.simpleName.asString()//获取类名
        val className = "My${originalClassName}"
        val file = environment.codeGenerator.createNewFile(//创建新的文件(默认.kt)
            Dependencies(
                true,
                classDeclaration.containingFile!!
            ), packageName, className
        )
        file.write("package $packageName\n\n".toByteArray())//写入文件
        file.write("class $className {\n".toByteArray())
        file.write("    val fields = ".toByteArray())
        val fields = classDeclaration.getAllProperties().map {//遍历所有的属性
            val name = it.simpleName.getShortName()//属性名
            val type = it.type.resolve().toString()//属性类型
            "$name: $type"
        }.joinToString()
        file.write("\"$fields ${environment.options["kspcompileargname"]}\"\n".toByteArray())
        file.write("}".toByteArray())
        file.close()
    }
}

/**
 * creator: lt  2022/10/20  lt.dygzs@qq.com
 * effect : 测试注解
 * warning:
 */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class TestKsp
